package cn.aliothstar.code;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.net.ftp.FTPClient;


import java.io.*;
import java.net.*;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import com.alibaba.fastjson.JSON;

/**
 * @作者：玉蘅
 * @项目名称：Three.java
 * @包名：cn.aliothstar.code
 * @文件名称：Four
 * @代码功能：第二阶段
 * @时间：2023/10/05/22:04
 */
public class Four {
    private static int checkCount = 0;
    private static final int THREAD_POOL_SIZE = 5;
    private static JSONArray serverArray = new JSONArray(); // 存储服务器信息
    private static int responseCode =0;

    public static void main(String[] args) {
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(THREAD_POOL_SIZE);
        executorService.scheduleAtFixedRate(new CheckServersTask(), 0, 10, TimeUnit.SECONDS);
    }

    private static class CheckServersTask implements Runnable {
        @Override
        public void run() {
            checkCount++; // 增加检测次数
            System.out.println("+++++++++++++++++++++++++++++");
            System.out.println("第 " + checkCount + " 次检查");
            System.out.println("+++++++++++++++++++++++++++++");

            // 从JSON文件中重新加载服务器信息
            reloadServerInfo();

            for (Object serverObj : serverArray) {
                JSONObject server = (JSONObject) serverObj;
                String serverName = server.getString("name");
                String serverAddress = server.getString("address");
                String adminEmail = server.getString("admin_email");

                System.out.println("检查的服务器为: " + serverAddress);

                if (isValidIPAddress(serverAddress)) {
                    System.out.println("这是一个IP地址.");
                    boolean isServerHealthy = checkServer(serverName, "http://" + serverAddress);
                    if (!isServerHealthy) {
                        // 服务器不正常，打印错误并通知管理员
                        System.out.println("\033[34;1m 服务器状态异常，请通知管理员: \033[0m" + "\033[35;1m" + adminEmail + "\033[0m");
                        // 获取服务器响应错误信息
                        String errorMessage = getServerErrorMessage("http://" + serverAddress);
                        // 服务器不正常，生成错误信息文件
                        generateErrorFile(serverName, serverAddress, adminEmail, responseCode, errorMessage);
                        System.out.println("--------------------------------");
                    }
                } else if (serverAddress.startsWith("http://")) {
                    System.out.println("这是一个HTTP地址.");
                    boolean isServerHealthy = checkServer(serverName, serverAddress);
                    if (!isServerHealthy) {
                        // 服务器不正常，打印错误并通知管理员
                        System.out.println("\033[34;1m 服务器状态异常，请通知管理员: \033[0m" + "\033[35;1m" + adminEmail + "\033[0m");
                        // 获取服务器响应错误信息
                        String errorMessage = getServerErrorMessage(serverAddress);
                        // 服务器不正常，生成错误信息文件
                        generateErrorFile(serverName, serverAddress, adminEmail, responseCode, errorMessage);
                        System.out.println("--------------------------------");
                    }
                } else if (serverAddress.startsWith("https://")) {
                    System.out.println("这是一个HTTPS地址.");
                    boolean isServerHealthy = checkServer(serverName, serverAddress);
                    if (!isServerHealthy) {
                        // 服务器不正常，打印错误并通知管理员
                        System.out.println("\033[34;1m 服务器状态异常，请通知管理员: \033[0m" + "\033[35;1m" + adminEmail + "\033[0m");
                        // 获取服务器响应错误信息
                        String errorMessage = getServerErrorMessage(serverAddress);
                        // 服务器不正常，生成错误信息文件
                        generateErrorFile(serverName, serverAddress, adminEmail, responseCode, errorMessage);
                        System.out.println("--------------------------------");
                    }
                } else {
                    System.out.println("无效的服务器格式: " + serverName);
                }
            }
        }

        // TODO 从JSON文件中重新加载服务器信息
        private void reloadServerInfo() {
            try (BufferedReader reader = new BufferedReader(new FileReader("resource/info.json"))) {
                StringBuilder jsonContent = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    jsonContent.append(line);
                }
                serverArray = JSON.parseArray(jsonContent.toString());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        // TODO 检测是否有效的IP地址
        private boolean isValidIPAddress(String address) {
            try {
                InetAddress.getByName(address);
                return true;
            } catch (Exception e) {
                return false;
            }
        }

        // TODO 检查服务器
        private boolean checkServer(String serverName, String serverURL) {
            try {
                long startTime = System.currentTimeMillis(); // 当前时间毫秒
                URL url = new URL(serverURL); // 服务器的地址
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                responseCode = connection.getResponseCode();
                long endTime = System.currentTimeMillis();
                long elapsedTime = endTime - startTime;

                System.out.println("服务器名称: " + serverName);
                System.out.println("响应码: " + responseCode);
                System.out.println("响应时间: " + elapsedTime + " ms");

                if (responseCode == HttpURLConnection.HTTP_OK) {
                    System.out.println("\033[32;1m 服务器正常 \033[0m");
                    System.out.println("--------------------------------");
                    return true;
                } else {
                    System.out.println("\033[31;1m无法访问服务器\033[0m");
                    return false;
                }
            } catch (IOException e) {
                System.out.println(e.getMessage());
                return false;
            }
        }

        /**
         * 获取服务器响应错误信息的方法
         */
        private String getServerErrorMessage(String serverURL) {
            try {
                URL url = new URL(serverURL);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                int responseCode = connection.getResponseCode();

                if (responseCode != HttpURLConnection.HTTP_OK) {
                    try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getErrorStream()))) {
                        StringBuilder errorMessage = new StringBuilder();
                        String line;
                        while ((line = reader.readLine()) != null) {
                            errorMessage.append(line);
                        }
                        return errorMessage.toString();
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return "无法获取服务器错误信息。";
        }

        // TODO 生成错误信息文件并上传到管理员服务器
        private void generateErrorFile(String serverName, String serverAddress, String adminEmail, int responseCode, String errorMessage) {
            try {
//                long startTime = System.currentTimeMillis(); // 当前时间毫秒
                String errorFileName = "error.log"; // 命名错误日志文件
                File errorFile = new File("resource/logs/" + errorFileName); // 项目文件夹存放文件

                // 如果文件不存在，则创建文件并写入头信息
                if (!errorFile.exists()) {
                    try (BufferedWriter headerWriter = new BufferedWriter(new FileWriter(errorFile))) {
                        headerWriter.write("错误日志文件\n");
                        // 可以在此处添加其他头信息
                    }
                }

                // 追加新的错误信息，并在每次写入时记录时间
                try (BufferedWriter writer = new BufferedWriter(new FileWriter(errorFile, true))) {
                    writer.write("时间: " + new Date() + "\n");
                    writer.write("服务器名称: " + serverName + "\n");
                    writer.write("服务器地址: " + serverAddress + "\n");
                    writer.write("管理员邮箱: " + adminEmail + "\n");
                    writer.write("响应码: " + responseCode + "\n");
                    writer.write("错误信息: " + errorMessage + "\n");
                    writer.write("线程执行信息: " + Thread.currentThread().getName() + "\n");
                    // 其他错误信息
                    writer.write("--------------------------------\n"); // 分隔不同条目
                }

                // 上传错误信息文件到管理员FTP服务器
                uploadErrorFileToAdminServer(errorFile);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        // 上传错误文件到管理服务器
        private void uploadErrorFileToAdminServer(File errorFile) {
            String adminServerAddress = "8.130.142.87"; // FTP服务器地址
            int adminServerPort = 21; // FTP服务器端口
            String adminServerUsername = "test"; // FTP服务器用户名
            String adminServerPassword = "12345678"; // FTP服务器密码
            String adminServerFolderPath = "/www/wwwroot/test/"; // FTP服务器目标文件夹

            FTPClient ftpClient = new FTPClient();
            try {
                // 连接到 FTP服务器
                ftpClient.connect(adminServerAddress, adminServerPort);
                if (ftpClient.login(adminServerUsername, adminServerPassword)) {
                    System.out.println("\033[32;1m FTP服务器登录成功 \033[0m");
                    ftpClient.enterLocalPassiveMode(); // 进入被动模式

                    // 切换到目标文件夹
                    ftpClient.changeWorkingDirectory(adminServerFolderPath);
                    // 上传文件
                    try (InputStream inputStream = new FileInputStream(errorFile)) {
                        boolean uploaded = ftpClient.storeFile(errorFile.getName(), inputStream);
//                        System.out.println(adminServerFolderPath + errorFile.getName());
                        if (uploaded) {
                            System.out.println("\033[32;1m 日志文件上传成功 \033[0m");
                        } else {
                            System.out.println("\033[31;1m 日志文件上传失败 \033[0m");
                        }
                    }

                    // 登出并断开连接
                    ftpClient.logout();
                    ftpClient.disconnect();
                } else {
                    System.out.println("\033[31;1m FTP登录失败 \033[0m");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

